package com.jin.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class JwtToken {

    private static String jwtKey;
    private static Integer expiredTimeIn;
    private static Integer defaultScope = 8;
    //把配置文件中的值注入到静态方法中
    @Value("${security.jwt-key}")
    public void setJwtKey(String jwtKey){
        JwtToken.jwtKey = jwtKey;
    }

    @Value("${security.token-expired-in}")
    public void setExpiredTimeIn(Integer expiredTimeIn) {
        JwtToken.expiredTimeIn = expiredTimeIn;
    }

    //检验token合不合法,合法就返回token里面的数据
    public static Optional<Map<String, Claim>> getClaims(String token){
        DecodedJWT  decodedJWT;
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        //解析
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            //通过jwtVerifier读取token
            decodedJWT = jwtVerifier.verify(token);
        }catch (JWTVerificationException e){
            return Optional.empty();
        }
        //获取token里面用户的Claims数据，不为空就返回
        return Optional.of(decodedJWT.getClaims());
    }


    //接收参数写入到jwt令牌里面去，要携带uid,还有Scope权限分级的数字
    //生成令牌的方法
    public static String makeToken(Long uid,Integer scope){
        return JwtToken.getToken(uid,scope);
    }

    public static String makeToken(Long uid){
        return JwtToken.getToken(uid,defaultScope);
    }

    //生成令牌的逻辑
    private static String getToken(Long uid,Integer scope){
        //首先选择算法
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        Map<String,Date> map = JwtToken.calculateExpiredIssues();
        //生成令牌
        String token = JWT.create()
                .withClaim("uid",uid)
                .withClaim("scope",scope)
                //签发时间
                .withIssuedAt(map.get("now"))
                //过期时间
                .withExpiresAt(map.get("expiredTime"))
                //生成令牌
                .sign(algorithm);
        return token;
    }

    //计算到期时间的方法
    private static Map<String, Date> calculateExpiredIssues() {
        Map<String, Date> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        //签发时间加上过期时间就是令牌到期时间
        calendar.add(Calendar.SECOND, JwtToken.expiredTimeIn);
        map.put("now", now);
        map.put("expiredTime", calendar.getTime());
        return map;
    }

    //验证token是否失效的方法
    public static Boolean verifyToken(String token){
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        //解析
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            jwtVerifier.verify(token);
        }catch (JWTVerificationException e){
            return false;
        }
        return true;
    }
}
